/***
 * @Author: 码上talk|RC
 * @Date: 2020-06-09 23:20:41
 * @LastEditTime: 2021-10-10 14:26:33
 * @LastEditors: 码上talk|RC
 * @Description: 
 * @FilePath: /tacomall-api/api/admin/src/main/java/store/tacomall/apiadmin/service/impl/TmStaffServiceImpl.java
 * @Just do what I think it is right
 */
package store.tacomall.apiadmin.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;

import store.tacomall.apiadmin.service.TmStaffService;
import store.tacomall.common.entity.tm.TmAccessRule;
import store.tacomall.common.entity.tm.TmDept;
import store.tacomall.common.entity.tm.TmJob;
import store.tacomall.common.entity.tm.TmStaff;
import store.tacomall.common.enumeration.BizEnum;
import store.tacomall.common.json.ResponseJson;
import store.tacomall.common.json.ResponsePageJson;
import store.tacomall.common.mapper.tm.TmAccessRuleMapper;
import store.tacomall.common.mapper.tm.TmDeptMapper;
import store.tacomall.common.mapper.tm.TmJobMapper;
import store.tacomall.common.mapper.tm.TmStaffMapper;
import store.tacomall.common.util.ExceptionUtil;
import store.tacomall.common.util.PasswordUtil;
import store.tacomall.common.util.StringUtil;

@Service
public class TmStaffServiceImpl extends ServiceImpl<TmStaffMapper, TmStaff> implements TmStaffService {

  @Autowired
  private TmAccessRuleMapper adminAuthRuleMapper;

  @Autowired
  private TmDeptMapper tmDeptMapper;

  @Autowired
  private TmJobMapper tmJobMapper;

  @Autowired
  TransactionDefinition transactionDefinition;

  @Autowired
  DataSourceTransactionManager dataSourceTransactionManager;

  @Override
  public ResponseJson<String> login(String username, String password) {
    ResponseJson<String> responseJson = new ResponseJson<>();
    try {
      Subject subject = SecurityUtils.getSubject();
      UsernamePasswordToken adminUser = new UsernamePasswordToken(username, PasswordUtil.encode(password));
      subject.login(adminUser);
      String authorization = (String) subject.getSession().getId();
      responseJson.setData(authorization);
      responseJson.ok();
    } catch (UnknownAccountException ue) {
      responseJson.setStatus(false);
      responseJson.setMessage("员工不存在");
    } catch (LockedAccountException le) {
      responseJson.setStatus(false);
      responseJson.setMessage("员工已冻结");
    } catch (IncorrectCredentialsException ie) {
      responseJson.setStatus(false);
      responseJson.setMessage("密码错误");
    }
    return responseJson;
  }

  @Override
  public ResponseJson<String> logout() {
    ResponseJson<String> responseJson = new ResponseJson<>();
    Subject subject = SecurityUtils.getSubject();
    subject.logout();
    responseJson.ok();
    return responseJson;
  }

  @Override
  public ResponseJson<TmStaff> info(JSONObject json) {
    ResponseJson<TmStaff> responseJson = new ResponseJson<>();
    TmStaff tmStaff = (TmStaff) SecurityUtils.getSubject().getPrincipal();
    LambdaQueryWrapper<TmStaff> lqw = new QueryWrapper<TmStaff>().lambda();
    JSONObject query = json.getJSONObject("query");
    if (ObjectUtil.isNotEmpty(query)) {
      if (ObjectUtil.isNotEmpty(query.getInteger("id"))) {
        lqw.eq(TmStaff::getId, query.getInteger("id"));
        lqw.eq(TmStaff::getIsDelete, 0);
        tmStaff = this.baseMapper.selectOne(lqw);
      } else {
        ExceptionUtil.throwClientException(BizEnum.REQUEST_QUERY_UNMATCH.getMessage());
      }
    }
    responseJson
        .setData(baseMapper.selectOne(new QueryWrapper<TmStaff>().lambda().eq(TmStaff::getId, tmStaff.getId())));
    responseJson.ok();
    return responseJson;
  }

  @Override
  public ResponseJson<List<TmAccessRule>> accessRuleList() {
    ResponseJson<List<TmAccessRule>> responseJson = new ResponseJson<>();
    TmStaff tmStaff = (TmStaff) SecurityUtils.getSubject().getPrincipal();
    TmDept tmDept = tmDeptMapper.selectById(tmStaff.getDeptId());
    TmJob tmJob = tmJobMapper.selectById(tmStaff.getJobId());
    responseJson.setData(new ArrayList<>());
    if (ObjectUtil.isNotNull(tmDept) && ObjectUtil.isNotEmpty(tmDept.getAccessRuleIds())) {
      responseJson.setData(adminAuthRuleMapper.selectList(new QueryWrapper<TmAccessRule>().lambda()
          .in(TmAccessRule::getId, Arrays.asList(tmDept.getAccessRuleIds().split(",")).stream().filter((String s) -> {
            if (ObjectUtil.isNotNull(tmJob) && ObjectUtil.isNotNull(tmJob.getIgnoreAccessRuleIds())
                && Arrays.asList(tmJob.getIgnoreAccessRuleIds().split(",")).contains(s)) {
              return false;
            }
            return true;
          }).collect(Collectors.toList()))));
    }
    responseJson.ok();
    return responseJson;
  }

  @Override
  public ResponsePageJson<List<TmStaff>> page(int pageIndex, int pageSize, JSONObject json) {
    ResponsePageJson<List<TmStaff>> responsePageVo = new ResponsePageJson<>();
    Page<TmStaff> page = new Page<>(pageIndex, pageSize);
    LambdaQueryWrapper<TmStaff> q = new QueryWrapper<TmStaff>().lambda();

    JSONObject query = json.getJSONObject("query");
    if (ObjectUtil.isNotEmpty(query) && ObjectUtil.isNotEmpty(query.get("keyword"))) {
      q.like(TmStaff::getNickname, query.get("keyword"));
    }
    if (ObjectUtil.isNotEmpty(query) && ObjectUtil.isNotEmpty(query.getInteger("deptId"))) {
      q.eq(TmStaff::getDeptId, query.getInteger("deptId"));
    }
    q.eq(TmStaff::getIsDelete, 0);
    IPage<TmStaff> result = this.baseMapper.queryPage(page, q);
    responsePageVo.setData(result.getRecords());
    responsePageVo.buildPage(result.getCurrent(), result.getSize(), result.getTotal());
    responsePageVo.ok();
    return responsePageVo;
  }

  @Override
  public ResponseJson<TmStaff> add(JSONObject json) {
    ResponseJson<TmStaff> responseJson = new ResponseJson<>();
    responseJson.setStatus(false);
    TmStaff tmStaff = JSON.toJavaObject(json, TmStaff.class);
    tmStaff.setPasswd(PasswordUtil.encode(tmStaff.getPasswd()));
    this.baseMapper.insert(tmStaff);
    responseJson.ok();
    responseJson.setData(tmStaff);
    return responseJson;
  }

  @Override
  public ResponseJson<TmStaff> update(int id, JSONObject json) {
    ResponseJson<TmStaff> responseJson = new ResponseJson<>();
    TmStaff oldTmStaff = baseMapper.selectById(id);
    TmStaff tmStaff = JSON.toJavaObject(json, TmStaff.class);

    if (StringUtil.isNotBlank(tmStaff.getPasswd())) {
      tmStaff.setPasswd(PasswordUtil.encode(tmStaff.getPasswd()));
    } else {
      tmStaff.setPasswd(oldTmStaff.getPasswd());
    }
    this.baseMapper.update(tmStaff, new UpdateWrapper<TmStaff>().lambda().eq(TmStaff::getId, id));
    responseJson.ok();
    responseJson.setData(tmStaff);
    return responseJson;
  }

}
